package com.example.client;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import androidx.annotation.NonNull;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;

public class SocketClient {
    private static final String TAG = "SocketClient";

    public static final int CONNECT_TIMEOUT= 5000;

    public static final int RETURN_MESSAGE = 0x1;

    public static final int CONNECT_ERROR = 0x2;

    public static final int DISCONNECT = 0x3;

    private Socket client;
    private Context context;
    private int port;
    private String ip;
    private Thread thread;
    public static Handler mHandler;
    private boolean isClient=false;
    private PrintWriter out;
    private InputStream in;
    private String str;
    private SendMsg2 mSendMs2;
    private Handler mSocketHander;
    private static final int SEND_FINISHED = 0x102;

    public static Handler ClientHandler;


    public SocketClient() {
        mSocketHander = new Handler() {
            @Override
            public void handleMessage(@NonNull Message msg) {
                super.handleMessage(msg);
                switch (msg.what) {
                    case SEND_FINISHED:
                        resetSendMsg();
                        break;
                }
            }
        };
    }

    public Socket getSocket(){
        return client;
    }

    //上下文，IP地址，端口号
    public void value(Context context, String ip, int port)
    {
        this.context=context;
        this.ip=ip;
        this.port=port;
    }

    //客户端连接线程，
    public void openClientThread(){
        new Thread() {
            @Override
            public void run() {
                try {
                    client = new Socket();
                    SocketAddress address = new InetSocketAddress(ip, port);
                    client.connect(address, CONNECT_TIMEOUT);
                    Log.i("连接线程里client信息", client.toString());     //正确
                    ReceiveMsg2();
                } catch (IOException e) {
                    e.printStackTrace();
                    notifyConnectError();

                }
            }
        }.start();
    }


    //客户端收到数据，返回到主界面
    public void returnMessage(byte[] bytes){
        Message msg=new Message();
        msg.what = RETURN_MESSAGE;
        msg.obj=bytes;
        if(ClientHandler != null) {
            ClientHandler.sendMessage(msg);
        }
    }

    private void notifyConnectError() {
        if (ClientHandler != null) {
            ClientHandler.sendEmptyMessage(CONNECT_ERROR);
        }
    }

    public void notifyDisconnect() {
        if (ClientHandler != null) {
            ClientHandler.sendEmptyMessage(DISCONNECT);
        }
    }

    //发送消息方法
    public void sendMsg2(final String str)
    {
        Log.d("发送方法",str);     //ok
        Log.d(TAG, "sendMsg2:方法要发往线程的clien "+client.toString());
        if (mSendMs2 == null) {
            if (isAvailable()) {
                mSendMs2 = new SendMsg2(client, str);
            }
            mSendMs2.start();
        }
    }

    private void resetSendMsg() {
        Log.d(TAG, "resetSendMsg");
        mSendMs2 = null;
    }

    //接收消息方法
    public void ReceiveMsg2()
    {
        Log.d("收到方法","");
        new ReceiveMsg2(client).start();
    }


    //接收消息线程
    class ReceiveMsg2 extends Thread{
        Socket response;

        public ReceiveMsg2(Socket response) {
            this.response = response;
        }

        @Override
        public void run() {
            try {
                Log.d("收到线程","");
                // String address = response.getInetAddress().getHostAddress();
                InputStream inputStream = response.getInputStream();//得到从服务端的输入流
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                byte[] buff = new byte[1024];
                int size = -1;
                while((size = inputStream.read(buff)) != -1) {
                    Log.d(TAG, "read buff start! size=" + size);
                    if (size > 0 && buff[size-1] == 10) {
                        baos.write(buff, 0, size - 1);
                        returnMessage(baos.toByteArray());
                        baos.reset();
                        Log.d(TAG, "read buff end!");
                        continue;
                    }
                    baos.write(buff, 0, size);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            close();
            notifyDisconnect();
        }
    }

    //发送消息的线程
    class SendMsg2 extends Thread{
        Socket response;
        String str;

        public SendMsg2(Socket response, String str) {
            this.response = response;
            Log.d(TAG, "SendMsg2: response信息:"+response.toString());
            this.str = str;
            Log.d(TAG, "SendMsg2: str信息"+str);
        }

        @Override
        public void run() {
            try {
                Log.d(TAG,"send str: " + str.length());      //1
                OutputStream outputStream = response.getOutputStream();//输出流，向客户端发送消息
                byte[] data = str.getBytes("UTF-8");
                int offset = 0;
                while(offset < data.length) {
                    int len = Math.min(data.length - offset, 1024);
                    outputStream.write(data, offset, len);
                    outputStream.flush();
                    offset += len;
                }
                outputStream.write("\n".getBytes("UTF-8"));
                outputStream.flush();
                //关闭相对应的资源
//            bufferedReader.close();
//            bufferedWriter.close();
//            outputStream.close();
//            response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            mSocketHander.sendEmptyMessage(SEND_FINISHED);
            Log.d(TAG, "sendEmptyMessage SEND_FINISHED!");
        }
    }

    public boolean isAvailable() {
        return client != null
                && client.isConnected()
                && !client.isInputShutdown()
                && !client.isOutputShutdown()
                && !client.isClosed();
    }

    public void close() {
        Log.d(TAG, "SocketClient is close!");
        if (client != null) {
            try {
                client.shutdownInput();
                client.shutdownOutput();
                client.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}
